<html>
<script>
/*
题目描述
函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments，返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型，不需考虑参数转换。 
输入例子:
useArguments(1, 2, 3, 4)
输出例子:
10

关于arguments的介绍(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments)

// 一般写法，直接利用arguments只有length属性的特点
*/
function useArguments1() {
    var sum = 0;
    for (var i = 0; i < arguments.length; ++i) {
        sum += arguments[i];
    }
    return sum;
}

// 转成数组 ([]为Array.prototype的语法糖)
function useArguments2() {
    var arr = [].slice.call(arguments); 
    return arr.reduce(function(a, b) {
        return a + b;
    });
}
/* call, bind, apply会改变生成函数对象的this, 使得arguments可以直接使用数组的方法,
   所以也可不转换成数组而直接使用reduce */

// call同上, 精简版
function useArguments3() {
    return [].reduce.call(arguments, function(a, b) {
        return a + b;
    });
}

// bind
function useArguments4() {
    return [].reduce.bind(arguments, function(a, b) {
        return a + b;
    })();
}

// apply
function useArguments5() {
    return [].reduce.apply(arguments, [function(a, b) {
        return a + b;
    }]);
}

// eval的妙用，但不推荐使用eval
function useArguments6() {
    var arr = Array.prototype.slice.call(arguments);
    return eval(arr.join('+'));
}

console.log(useArguments1(1,2,3,4));
console.log(useArguments2(1,2,3,4));
console.log(useArguments3(1,2,3,4));
console.log(useArguments4(1,2,3,4));
console.log(useArguments5(1,2,3,4));
console.log(useArguments6(1,2,3,4));

/*
题目描述
实现函数 partialUsingArguments，调用之后满足如下条件：
1、返回一个函数 result
2、调用 result 之后，返回的结果与调用函数 fn 的结果一致
3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数 
输入例子:
var a = 1; 
var b = 2; 
var c = 3; 
var d = 4;
var test = function (first, second, third, forth) {
   return first + second + third + forth;
};
partialUsingArguments(test, a, b)(c, d);
输出例子:
10

*/
function partialUsingArguments(fn) {
    var arr = [].slice.call(arguments, 1); 
    /* arr是由partialUsingArguments传的arguments转换而来 */
    
    function result() {
        var arrFromResult = [].slice.call(arguments);
        /* arrFromResult则从函数result中传的arguments转换, 所以不能在result外获取 */
        return fn.apply(null, arr.concat(arrFromResult));
    }

    return result;
}

// 稍微简化，跟上面差不多
function partialUsingArguments2(fn) {
    var arr = [].slice.call(arguments, 1);
    
    return function() {
        return fn.apply(this, arr.concat([].slice.call(arguments)));
    }
}

let a = 10; 
let b = 2; 
let c = 3; 
let d = 4;
var test2 = function (first, second, third, forth) {
   return first + second + third + forth;
};
console.log(partialUsingArguments(test2, a, b)(c, d));

</script>
</html>